package org.thunms.framework.utils;

import java.text.ParseException;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

import com.ibm.icu.util.Calendar;

/**
 * 日期工具类
 * 
 * 
 * 
 */
public class UtilDate {

	/**
	 * 将Date类型转换为字符串
	 * 
	 * @param date
	 *            日期类型
	 * @return 日期字符串
	 */
	public static String format(Date date) {
		return format(date, "yyyy-MM-dd HH:mm:ss");
	}

	/**
	 * 将Date类型转换为字符串
	 * 
	 * @param date
	 *            日期类型
	 * @param pattern
	 *            字符串格式
	 * @return 日期字符串
	 */
	public static String format(Date date, String pattern) {
		if (date == null) {
			return "null";
		}
		if (pattern == null || pattern.equals("") || pattern.equals("null")) {
			pattern = "yyyy-MM-dd HH:mm:ss";
		}
		return new java.text.SimpleDateFormat(pattern).format(date);
	}

	/**
	 * 将字符串转换为Date类型
	 * 
	 * @param date
	 *            字符串类型
	 * @return 日期类型
	 */
	public static Date format(String date) {
		return format(date, null);
	}

	/**
	 * 将字符串转换为Date类型
	 * 
	 * @param date
	 *            字符串类型
	 * @param pattern
	 *            格式
	 * @return 日期类型
	 */
	public static Date format(String date, String pattern) {
		if (pattern == null || pattern.equals("") || pattern.equals("null")) {
			pattern = "yyyy-MM-dd HH:mm:ss";
		}
		if (date == null || date.equals("") || date.equals("null")) {
			return new Date();
		}
		Date d = null;
		try {
			d = new java.text.SimpleDateFormat(pattern).parse(date);
		} catch (ParseException pe) {
		}
		return d;
	}
	
	
	/**
	 * 根据传入的月份计算上一月
	 * @param monthNumber
	 * @return
	 */
	public static String getLastMonthNumber(String monthNumber){
		int m=Integer.parseInt(monthNumber);
		if(m>1){
			return (m-1)+"";
		}else{
			return "12";
		}
	}
	/**
	 * 根据传入的年月,返回上一年.例如：传入2014-01，则上一年为2013
	 * @param yearNumber
	 * @param monthNumber
	 * @return
	 */
	public static String getLastYearNumber(String yearNumber,String monthNumber){
		int m=Integer.parseInt(monthNumber);
		if(m>1){
			return yearNumber;
		}else{
			int y=Integer.parseInt(yearNumber);
			return (y-1)+"";
		}
	}
	
	/**
	 * 获取传入月份的下一月
	 * @param monthNumber
	 * @return
	 */
	public static String getNextMonthNumber(String monthNumber){
		int m=Integer.parseInt(monthNumber);
		if(m<12){
			return (m+1)+"";
		}else{
			return "1";
		}
	}
	/**
	 * 根据传入的年月,返回下一年.例如：传入2014-12，则上一年为2015
	 * @param yearNumber
	 * @param monthNumber
	 * @return
	 */
	public static String getNextYearNumber(String yearNumber,String monthNumber){
		int m=Integer.parseInt(monthNumber);
		if(m<12){
			return yearNumber;
		}else{
			int y=Integer.parseInt(yearNumber);
			return (y+1)+"";
		}
	}
	 /**
     * 以下是java.util.date处理工具方法
     */
    /**
     * returns a week number in a year for a Date input
     *
     * @param input Date date
     * @return A int containing the week number
     */
	public static Calendar toCalendar(Date stamp) {
        Calendar cal = Calendar.getInstance();
        if (stamp != null) {
            cal.setTime(stamp);
        }
        return cal;
    }
    
    public static Calendar toCalendar(Long time) {
        Calendar cal = Calendar.getInstance();
        if (time != null) {
            cal.setTimeInMillis(time);
        }
        return cal;
    }
    public static Calendar getCalendarInstance(TimeZone timeZone, Locale locale) {
        return Calendar.getInstance(com.ibm.icu.util.TimeZone.getTimeZone(timeZone.getID()), locale);
    }
    public static Calendar toCalendar(Date date, TimeZone timeZone, Locale locale) {
        Calendar cal = getCalendarInstance(timeZone, locale);
        if (date != null) {
            cal.setTime(date);
        }
        return cal;
    }
    /**
     * returns a day number in a week for a Date input
     *
     * @param stamp Date date
     * @return A int containing the day number (sunday = 1, saturday = 7)
     */
    public static int dayNumber(Date stamp) {
        Calendar tempCal = toCalendar(stamp, TimeZone.getDefault(), Locale.getDefault());
        return tempCal.get(Calendar.DAY_OF_WEEK);
    }

    public static int weekNumber(Date input, int startOfWeek) {
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(startOfWeek);

        if (startOfWeek == Calendar.MONDAY) {
           calendar.setMinimalDaysInFirstWeek(4);
        } else if (startOfWeek == Calendar.SUNDAY) {
           calendar.setMinimalDaysInFirstWeek(3);
        }

        calendar.setTime(new java.util.Date(input.getTime()));
        return calendar.get(Calendar.WEEK_OF_YEAR);
    }

  
    public static Date getNextDayStart(Date stamp) {
	    return getDayStart(stamp, 1);
	}

	/**
     * Perform date/time arithmetic on a Date. This is the only accurate way to
     * perform date/time arithmetic across locales and time zones.
     *
     * @param stamp date/time to perform arithmetic on
     * @param adjType the adjustment type to perform. Use one of the java.util.Calendar fields.
     * @param adjQuantity the adjustment quantity.
     * @param timeZone
     * @param locale
     * @return adjusted Date
     * @see java.util.Calendar
     */
    public static Date getDateStart(Date stamp) {
        return getDateStart(stamp,0,0,0,0);
    }
    /**
     * 当前时间N小时后的时间
     * @param stamp
     * @param hoursLater
     * @return
     */
    public static Date getDateStart(Date stamp,int hoursLater) {
        return getDateStart(stamp,0,hoursLater);
    }
    /**
     * 当前时间N天N小时后的时间
     * @param stamp
     * @param hoursLater
     * @return
     */
    public static Date getDateStart(Date stamp,int daysLater,int hoursLater) {
        return getDateStart(stamp,0,daysLater, hoursLater);
    }
    /**
     * 当前时间N月N天N小时后的时间
     * @param stamp
     * @param hoursLater
     * @return
     */
    public static Date getDateStart(Date stamp,int monthsLater,int daysLater,int hoursLater) {
        return getDateStart(stamp,0,monthsLater,daysLater, hoursLater, TimeZone.getDefault(), Locale.getDefault());
    }
    /**
     * 当前时间N年N月N天N小时后的时间
     * @param stamp
     * @param hoursLater
     * @return
     */
    public static Date getDateStart(Date stamp,int yearsLater,int monthsLater,int daysLater,int hoursLater) {
        return getDateStart(stamp,yearsLater,monthsLater,daysLater, hoursLater, TimeZone.getDefault(), Locale.getDefault());
    }
    /**
     * Return a Date for right now
     *
     * @return Date for right now
     */
   
    public static Date getDayStart(Date stamp) {
        return getDayStart(stamp, 0);
    }

    public static Date getDayStart(Date stamp, int daysLater) {
        return getDayStart(stamp, daysLater, TimeZone.getDefault(), Locale.getDefault());
    }

    public static Date getDayEnd(Date stamp) {
        return getDayEnd(stamp, Long.valueOf(0));
    }

    public static Date getDayEnd(Date stamp, Long daysLater) {
        return getDayEnd(stamp, daysLater, TimeZone.getDefault(), Locale.getDefault());
    }

    /**
     * Return the date for the first day of the year
     *
     * @param stamp
     * @return Date
     */
    public static Date getYearStart(Date stamp) {
        return getYearStart(stamp, 0, 0, 0);
    }
    public static Date getNextYearStart(Date stamp) {
        return getYearStart(stamp, 0, 0, 1);
    }
    public static Date getYearStart(Date stamp, int daysLater) {
        return getYearStart(stamp, daysLater, 0, 0);
    }

    public static Date getYearStart(Date stamp, int daysLater, int yearsLater) {
        return getYearStart(stamp, daysLater, 0, yearsLater);
    }
    public static Date getYearStart(Date stamp, int daysLater, int monthsLater, int yearsLater) {
        return getYearStart(stamp, daysLater, monthsLater, yearsLater, TimeZone.getDefault(), Locale.getDefault());
    }
    public static Date getYearStart(Date stamp, Number daysLater, Number monthsLater, Number yearsLater) {
        return getYearStart(stamp, (daysLater == null ? 0 : daysLater.intValue()),
                (monthsLater == null ? 0 : monthsLater.intValue()), (yearsLater == null ? 0 : yearsLater.intValue()));
    }

    /**
     * Return the date for the first day of the month
     *
     * @param stamp
     * @return Date
     */
    
    public static Date getNextMonthStart(Date stamp) {
        return getMonthStart(stamp, 0, 1);
    }
    public static Date getMonthStart(Date stamp) {
        return getMonthStart(stamp, 0, 0);
    }

    public static Date getMonthStart(Date stamp, int daysLater) {
        return getMonthStart(stamp, daysLater, 0);
    }

    public static Date getMonthStart(Date stamp, int daysLater, int monthsLater) {
        return getMonthStart(stamp, daysLater, monthsLater, TimeZone.getDefault(), Locale.getDefault());
    }

    public static int weekNumber(Date input) {
	    return weekNumber(input, TimeZone.getDefault(), Locale.getDefault());
	}

	/**
     * Return the date for the first day of the week
     *
     * @param stamp
     * @return Date
     */
    public static Date getWeekStart(Date stamp) {
        return getWeekStart(stamp, 0, 0);
    }

    public static Date getWeekStart(Date stamp, int daysLater) {
        return getWeekStart(stamp, daysLater, 0);
    }

    public static Date getWeekStart(Date stamp, int daysLater, int weeksLater) {
        return getWeekStart(stamp, daysLater, weeksLater, TimeZone.getDefault(), Locale.getDefault());
    }

    public static Date getWeekEnd(Date stamp) {
        return getWeekEnd(stamp, TimeZone.getDefault(), Locale.getDefault());
    }

    
    public static Date adjustTimestamp(Date stamp, int adjType, int adjQuantity, TimeZone timeZone, Locale locale) {
        Calendar tempCal = toCalendar(stamp, timeZone, locale);
        tempCal.add(adjType, adjQuantity);
        return new Date(tempCal.getTimeInMillis());
    }

    public static Date adjustTimestamp(Date stamp, Integer adjType, Integer adjQuantity) {
        Calendar tempCal = toCalendar(stamp);
        tempCal.add(adjType, adjQuantity);
        return new Date(tempCal.getTimeInMillis());
    }

    public static Date getDayStart(Date stamp, TimeZone timeZone, Locale locale) {
        return getDayStart(stamp, 0, timeZone, locale);
    }

    public static Date getDayStart(Date stamp, int daysLater, TimeZone timeZone, Locale locale) {
        Calendar tempCal = toCalendar(stamp, timeZone, locale);
        tempCal.set(tempCal.get(Calendar.YEAR), tempCal.get(Calendar.MONTH), tempCal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        tempCal.add(Calendar.DAY_OF_MONTH, daysLater);
       
        return tempCal.getTime();
    }
    public static Date getDateStart(Date stamp,int yearsLater,int monthsLater,int daysLater, int hoursLater, TimeZone timeZone, Locale locale) {
        Calendar tempCal = toCalendar(stamp, timeZone, locale);
        tempCal.add(Calendar.YEAR, yearsLater);
        tempCal.add(Calendar.MONTH, monthsLater);
        tempCal.add(Calendar.DATE, daysLater);
        tempCal.add(Calendar.HOUR, hoursLater);
        return tempCal.getTime();
    }

    public static Date getDayEnd(Date stamp, TimeZone timeZone, Locale locale) {
        return getDayEnd(stamp, Long.valueOf(0), timeZone, locale);
    }

    public static Date getDayEnd(Date stamp, Long daysLater, TimeZone timeZone, Locale locale) {
        Calendar tempCal = toCalendar(stamp, timeZone, locale);
        tempCal.set(tempCal.get(Calendar.YEAR), tempCal.get(Calendar.MONTH), tempCal.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
        tempCal.add(Calendar.DAY_OF_MONTH, daysLater.intValue());
        return tempCal.getTime();
    }

    public static Date getWeekStart(Date stamp, TimeZone timeZone, Locale locale) {
        return getWeekStart(stamp, 0, 0, timeZone, locale);
    }

    public static Date getWeekStart(Date stamp, int daysLater, TimeZone timeZone, Locale locale) {
        return getWeekStart(stamp, daysLater, 0, timeZone, locale);
    }

    public static Date getWeekStart(Date stamp, int daysLater, int weeksLater, TimeZone timeZone, Locale locale) {
        Calendar tempCal = toCalendar(stamp, timeZone, locale);
        tempCal.set(tempCal.get(Calendar.YEAR), tempCal.get(Calendar.MONTH), tempCal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        tempCal.add(Calendar.DAY_OF_MONTH, daysLater);
        tempCal.set(Calendar.DAY_OF_WEEK, tempCal.getFirstDayOfWeek());
        tempCal.add(Calendar.WEEK_OF_MONTH, weeksLater);
        return tempCal.getTime();
    }

    public static Date getWeekEnd(Date stamp, TimeZone timeZone, Locale locale) {
        Date weekStart = getWeekStart(stamp, timeZone, locale);
        Calendar tempCal = toCalendar(weekStart, timeZone, locale);
        tempCal.add(Calendar.DAY_OF_MONTH, 6);
        return getDayEnd(new Date(tempCal.getTimeInMillis()), timeZone, locale);
    }

    public static Date getMonthStart(Date stamp, TimeZone timeZone, Locale locale) {
        return getMonthStart(stamp, 0, 0, timeZone, locale);
    }

    public static Date getMonthStart(Date stamp, int daysLater, TimeZone timeZone, Locale locale) {
        return getMonthStart(stamp, daysLater, 0, timeZone, locale);
    }

    public static Date getMonthStart(Date stamp, int daysLater, int monthsLater, TimeZone timeZone, Locale locale) {
        Calendar tempCal = toCalendar(stamp, timeZone, locale);
        tempCal.set(tempCal.get(Calendar.YEAR), tempCal.get(Calendar.MONTH), 1, 0, 0, 0);
        tempCal.add(Calendar.MONTH, monthsLater);
        tempCal.add(Calendar.DAY_OF_MONTH, daysLater);
        return tempCal.getTime();
    }

    public static Date getMonthEnd(Date stamp, TimeZone timeZone, Locale locale) {
        Calendar tempCal = toCalendar(stamp, timeZone, locale);
        tempCal.set(tempCal.get(Calendar.YEAR), tempCal.get(Calendar.MONTH), tempCal.getActualMaximum(Calendar.DAY_OF_MONTH), 0, 0, 0);
        return getDayEnd(new Date(tempCal.getTimeInMillis()), timeZone, locale);
    }

    public static Date getYearStart(Date stamp, TimeZone timeZone, Locale locale) {
        return getYearStart(stamp, 0, 0, 0, timeZone, locale);
    }

    public static Date getYearStart(Date stamp, int daysLater, TimeZone timeZone, Locale locale) {
        return getYearStart(stamp, daysLater, 0, 0, timeZone, locale);
    }

    public static Date getYearStart(Date stamp, int daysLater, int yearsLater, TimeZone timeZone, Locale locale) {
        return getYearStart(stamp, daysLater, 0, yearsLater, timeZone, locale);
    }

    public static Date getYearStart(Date stamp, Number daysLater, Number monthsLater, Number yearsLater, TimeZone timeZone, Locale locale) {
        return getYearStart(stamp, (daysLater == null ? 0 : daysLater.intValue()),
                (monthsLater == null ? 0 : monthsLater.intValue()), (yearsLater == null ? 0 : yearsLater.intValue()), timeZone, locale);
    }

    public static Date getYearStart(Date stamp, int daysLater, int monthsLater, int yearsLater, TimeZone timeZone, Locale locale) {
        Calendar tempCal = toCalendar(stamp, timeZone, locale);
        tempCal.set(tempCal.get(Calendar.YEAR), Calendar.JANUARY, 1, 0, 0, 0);
        tempCal.add(Calendar.YEAR, yearsLater);
        tempCal.add(Calendar.MONTH, monthsLater);
        tempCal.add(Calendar.DAY_OF_MONTH, daysLater);
        return tempCal.getTime();
    }

    public static Date getYearEnd(Date stamp, TimeZone timeZone, Locale locale) {
        Calendar tempCal = toCalendar(stamp, timeZone, locale);
        tempCal.set(tempCal.get(Calendar.YEAR), tempCal.getActualMaximum(Calendar.MONTH) + 1, 0, 0, 0, 0);
        return getMonthEnd(new Date(tempCal.getTimeInMillis()), timeZone, locale);
    }

    public static int weekNumber(Date stamp, TimeZone timeZone, Locale locale) {
        Calendar tempCal = toCalendar(stamp, timeZone, locale);
        return tempCal.get(Calendar.WEEK_OF_YEAR);
    }

  

    public static int getSecond(Date stamp, TimeZone timeZone, Locale locale) {
        Calendar cal = UtilDateTime.toCalendar(stamp, timeZone, locale);
        return cal.get(Calendar.SECOND);
    }

    public static int getMinute(Date stamp, TimeZone timeZone, Locale locale) {
        Calendar cal = UtilDateTime.toCalendar(stamp, timeZone, locale);
        return cal.get(Calendar.MINUTE);
    }

    public static int getHour(Date stamp, TimeZone timeZone, Locale locale) {
        Calendar cal = UtilDateTime.toCalendar(stamp, timeZone, locale);
        return cal.get(Calendar.HOUR_OF_DAY);
    }

    public static int getDayOfWeek(Date stamp, TimeZone timeZone, Locale locale) {
        Calendar cal = UtilDateTime.toCalendar(stamp, timeZone, locale);
        return cal.get(Calendar.DAY_OF_WEEK);
    }

    public static int getDayOfMonth(Date stamp, TimeZone timeZone, Locale locale) {
        Calendar cal = UtilDateTime.toCalendar(stamp, timeZone, locale);
        return cal.get(Calendar.DAY_OF_MONTH);
    }

    public static int getDayOfYear(Date stamp, TimeZone timeZone, Locale locale) {
        Calendar cal = UtilDateTime.toCalendar(stamp, timeZone, locale);
        return cal.get(Calendar.DAY_OF_YEAR);
    }

    public static int getWeek(Date stamp, TimeZone timeZone, Locale locale) {
        Calendar cal = UtilDateTime.toCalendar(stamp, timeZone, locale);
        return cal.get(Calendar.WEEK_OF_YEAR);
    }

    public static int getMonth(Date stamp, TimeZone timeZone, Locale locale) {
        Calendar cal = UtilDateTime.toCalendar(stamp, timeZone, locale);
        return cal.get(Calendar.MONTH);
    }

    public static int getYear(Date stamp, TimeZone timeZone, Locale locale) {
        Calendar cal = UtilDateTime.toCalendar(stamp, timeZone, locale);
        return cal.get(Calendar.YEAR);
    }
    
    //#####################################################
    /**
     * 毫秒转化
     * @param ms 毫秒
     * @return 分钟、秒
     */
    public static String formatTime(long ms) {
                
                 int ss = 1000;
                 int mi = ss * 60;
                 int hh = mi * 60;
                 //int dd = hh * 24;

                 
                 long hour = ms / hh;
                 long minute = (ms -  hour * hh) / mi;
                 long second = (ms - hour * hh - minute * mi) / ss;
                 long milliSecond = ms -  hour * hh - minute * mi - second * ss;

                 //String strDay = day < 10 ? "0" + day : "" + day; //天
                 String strHour = hour < 10 ? "0" + hour : "" + hour;//小时
                 String strMinute = minute < 10 ? "0" + minute : "" + minute;//分钟
                 String strSecond = second < 10 ? "0" + second : "" + second;//秒
                 String strMilliSecond = milliSecond < 10 ? "0" + milliSecond : "" + milliSecond;//毫秒
                 strMilliSecond = milliSecond < 100 ? "0" + strMilliSecond : "" + strMilliSecond;
                
                 return strHour+"小时"+strMinute + "分钟 " + strSecond + "秒";
       }
   /**
    * 毫秒转化时分秒毫秒
    * @param ms 传入毫秒
    * @return 天、小时、分、秒、毫秒
    */
    public static String formatTime(Long ms) {
        Integer ss = 1000;
        Integer mi = ss * 60;
        Integer hh = mi * 60;
        Integer dd = hh * 24;

        Long day = ms / dd;
        Long hour = (ms - day * dd) / hh;
        Long minute = (ms - day * dd - hour * hh) / mi;
        Long second = (ms - day * dd - hour * hh - minute * mi) / ss;
        Long milliSecond = ms - day * dd - hour * hh - minute * mi - second * ss;
        
        StringBuffer sb = new StringBuffer();
        if(day > 0) {
            sb.append(day+"天");
        }
        if(hour > 0) {
            sb.append(hour+"小时");
        }
        if(minute > 0) {
            sb.append(minute+"分");
        }
        if(second > 0) {
            sb.append(second+"秒");
        }
        if(milliSecond > 0) {
            sb.append(milliSecond+"毫秒");
        }
        return sb.toString();
    }
    
   
	}
